using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;

namespace TidhiGanitam.DataModel
{
    public class TidhiRoutineItem
    {
        private int m_Year;
        DateTime m_Date;
        private int m_SNo;
        ArrayList m_RaviRoutines;
        ArrayList m_ChandraRoutines;
        ArrayList m_DinamuRoutines;
        ArrayList m_TidhuluDetails;
        Rasi m_TidhiTime;
        double m_CurrentTidhi;
        int m_CurrentMasamu;
        Enums.TidhiState m_PreviousTidhiState;
        Enums.TidhiState m_CurrentTidhiState;
        double m_KaranamuTidhi;
        YearDetails m_CurrentyearDetails;
        bool m_IsAdhikaMasamu;

        public bool IsAdhikaMasamuRunning
        {
            get
            { return m_IsAdhikaMasamu; }
            set
            { m_IsAdhikaMasamu = value; }
        }
        public int Bhagam
        {
            get { return m_SNo; }
        }

        public DateTime Date
        {
            get { return m_Date; }
        }
        public Rasi TidhiTime
        {
            get { return m_TidhiTime; }
        }
        public ArrayList TidhuluDetails
        {
            get
            { return m_TidhuluDetails; }
            set
            {
                m_TidhuluDetails = value;
            }
        }
        public double KaranamuTidhi
        {
            get
            { return m_KaranamuTidhi; }
        }
        public double CurrentTidhi
        {
            get
            { return m_CurrentTidhi; }
            set
            { m_CurrentTidhi = value; }

        }
        public int CurrentMasamu
        {
            get
            { return m_CurrentMasamu; }
            set
            { m_CurrentMasamu = value; }
        }
        public Enums.TidhiState PreviousTidhiState
        {
            get
            { return m_PreviousTidhiState; }
        }
        public Enums.TidhiState CurrentTidhiState
        {
            get
            { return m_CurrentTidhiState; }
        }
        public TidhiRoutineItem(int SNo, int Year, DateTime Date,double currentTidhi, int currentMasamu,
            Enums.TidhiState previousTidhiState, ArrayList RaviRoutines,
            ArrayList ChandraRoutines, ArrayList DinamuRoutines, YearDetails CurrentYearDetails)
        {
            m_SNo = SNo;
            m_Year = Year;
            m_Date = Date;
            m_TidhuluDetails = new ArrayList();
            m_CurrentTidhi = currentTidhi;
            m_CurrentMasamu = currentMasamu;
            m_PreviousTidhiState = previousTidhiState;
            m_RaviRoutines = RaviRoutines;
            m_ChandraRoutines = ChandraRoutines;
            m_DinamuRoutines = DinamuRoutines;
            m_CurrentyearDetails = new YearDetails(CurrentYearDetails);
        }
        public void Calculate(bool CheckingForEshyam, TidhiRoutineItem PreviousTidhiRoutine, DinamuRoutineItem PreviousDinamu)
        {
            double dSign = 1;
            Rasi SpastaChandra = new Rasi(((ChandraRoutineItem)m_ChandraRoutines[m_SNo]).SpastaChandrudu);
            Rasi SpastaRavi = new Rasi(((RaviRoutineItem)m_RaviRoutines[m_SNo]).MadyamaRavi);
            Rasi SpastaChandraGati = new Rasi(((ChandraRoutineItem)m_ChandraRoutines[m_SNo]).ChandraDinaGatiPhalam);
            Rasi SpastaRaviGati = new Rasi(((RaviRoutineItem)m_RaviRoutines[m_SNo]).Gati);
            DinamuRoutineItem CurrentDinamuRoutine = (DinamuRoutineItem)m_DinamuRoutines[m_SNo];
            m_IsAdhikaMasamu = PreviousTidhiRoutine.IsAdhikaMasamuRunning;
            #region Tidhulu calculation
            // 1. Spasta Chandrudu - Spasta Ravi
            Rasi m_ChandraRaviDiff = SpastaChandra - SpastaRavi;
            // 2. Spasta Chandra Gati - Spasta Ravi Gati
            Rasi m_ChandraRaviGatiDiff = SpastaChandraGati - SpastaRaviGati;
            // 3. Find Starting Tidhi
            Double dTidhiIndex = MathHelper.GetDegrees(((Rasi)(m_ChandraRaviDiff / Constants.TidhiPramanam)).RawValue);
            if (m_SNo == 0 && !CheckingForEshyam)
            {
                m_CurrentTidhi = dTidhiIndex;
            }
            // 4. Find Advancement
            Rasi TidhiAdvancement = m_ChandraRaviDiff - (Constants.TidhiPramanam * dTidhiIndex);
            Rasi TidhiRemining = new Rasi(TidhiAdvancement);
            // 5. If Advancement is more than 1/4 of Tidhi, subtract from 12-00-00; Sign here is Add
            //      Else we dont have to subtract from 12-0-0; Sign will be Subtract : -1

            // Note: Here we may have to do some adjustments as when previous tidhi is puti, we need not check
            // whether curernt tidhi advancement is more than quarter tidhi.
            if (TidhiAdvancement >= Constants.QuarterTidhi && (m_PreviousTidhiState != Enums.TidhiState.Purti) &&
                (m_PreviousTidhiState != Enums.TidhiState.NextdayEshyamAdjustment))
            {
                TidhiRemining = Constants.TidhiPramanam - TidhiAdvancement;
            }
            else
            {
                /* Adjustments checking should be done here */
                Rasi CurTdiInPrvDay = new Rasi();
                Rasi CurTdiInCrrDay = new Rasi();
                Rasi TotalTdi = new Rasi();

                if (m_PreviousTidhiState != Enums.TidhiState.Purti)
                {
                    CurTdiInPrvDay = PreviousDinamu.RojuPramanam - PreviousTidhiRoutine.TidhiTime;
                }
                else
                {
                    CurTdiInPrvDay = PreviousDinamu.RojuPramanam;
                }
                CurTdiInCrrDay = new Rasi(TidhiRemining / m_ChandraRaviGatiDiff);
                TotalTdi = CurTdiInPrvDay + CurTdiInCrrDay;
                if ((TotalTdi < new Rasi(0, 0, 35))) //|| (CurTdiInCrrDay > CurrentDinamuRoutine.Dinardhamu)
                {
                    TidhiRemining = Constants.TidhiPramanam - TidhiAdvancement;
                }
                else
                {
                    dSign = -1;
                }
            }
            //Another adjustment is if when Tidhi 
            // 6. Divide Chandra Ravi diff with Gati Difference
            Rasi TidhiTime = TidhiRemining / m_ChandraRaviGatiDiff;

            // 7. Add this to dinardham. We consider the sign here
            m_TidhiTime = CurrentDinamuRoutine.Dinardhamu + (TidhiTime * dSign);

            //Just check yogamu time is -ve, make it +ve value
            if (m_TidhiTime < new Rasi(0, 0, 0))
            {
                m_TidhiTime = new Rasi(m_TidhiTime * -1); //just to make the value +ve
            }
            // if the
            if (m_CurrentTidhi < 0)
            {
                m_CurrentTidhi = dTidhiIndex;
            }

            // 8. Find out if tidhi spans entire day
            if (m_TidhiTime > CurrentDinamuRoutine.RojuPramanam)
            {
                if (!CheckingForEshyam)
                {
                    TidhiDetails PurtiTidhi = new TidhiDetails(m_CurrentMasamu, m_CurrentTidhi, Enums.TidhiState.Purti, m_Date, CurrentDinamuRoutine.RojuPramanam, m_IsAdhikaMasamu);
                    m_TidhuluDetails.Add(PurtiTidhi);
                    m_PreviousTidhiState = Enums.TidhiState.Purti;
                    m_KaranamuTidhi = m_CurrentTidhi;
                }
            }
            else
            {
                //9. Tidhi completed. add this tidhi to arraylist
                TidhiDetails NormalTidhi = new TidhiDetails(m_CurrentMasamu, m_CurrentTidhi, Enums.TidhiState.Ending, m_Date, new Rasi(m_TidhiTime), m_IsAdhikaMasamu);
                m_TidhuluDetails.Add(NormalTidhi);
                m_PreviousTidhiState = Enums.TidhiState.Ending;
                //For karanam values, we consider the current tidhi. so store this value before increment.
                m_KaranamuTidhi = m_CurrentTidhi;
                // Increment the tidhi and masamu
                IncrementTidhiMasamu();

                // 9. Find out if Eshyam is present
                Rasi StartTidhiTimeSpan = CurrentDinamuRoutine.RojuPramanam - m_TidhiTime;
                if (!CheckingForEshyam)
                {
                    if (CheckForEshyam(m_SNo, StartTidhiTimeSpan, CurrentMasamu, CurrentTidhi, m_PreviousTidhiState))
                    {
                        Rasi EshyamTidhiTime = Constants.TidhiPramanam / m_ChandraRaviGatiDiff;
                        if (EshyamTidhiTime < StartTidhiTimeSpan)
                        {
                            m_TidhiTime = new Rasi(EshyamTidhiTime);
                            TidhiDetails EshyamTidhi = new TidhiDetails(m_CurrentMasamu, m_CurrentTidhi, Enums.TidhiState.Eshyam, m_Date, new Rasi(m_TidhiTime), m_IsAdhikaMasamu);
                            m_TidhuluDetails.Add(EshyamTidhi);
                            m_PreviousTidhiState = Enums.TidhiState.Eshyam;
                            // Increment the tidhi and masamu
                            IncrementTidhiMasamu();
                        }
                        else
                        {
                            m_PreviousTidhiState = Enums.TidhiState.NextdayEshyamAdjustment;
                        }
                    }
                }
            }
            #endregion


        }

        private void IncrementTidhiMasamu()
        {
            if (m_SNo == 0)
            {
                m_CurrentMasamu = (m_CurrentTidhi < 5) ? 0 : 11;
            }
            m_CurrentTidhi++; //tidhi completed. so increment the tidhi
            m_CurrentTidhi = m_CurrentTidhi % 30;
            if (m_CurrentTidhi == 0)
            {
                if (!m_IsAdhikaMasamu)
                {
                    m_CurrentMasamu++;
                    m_CurrentMasamu = m_CurrentMasamu % 12;
                }
                if (m_CurrentyearDetails.AdhikaMasamu == m_CurrentMasamu)
                {
                    if (!m_IsAdhikaMasamu)
                    {
                        m_IsAdhikaMasamu = true;
                    }
                    else
                    {
                        m_IsAdhikaMasamu = false;
                    }
                }

            }
        }
        private bool CheckForEshyam(int CurrentPadakam, Rasi CurrentTime, int CurrentMasam, double CurrentTidhi, Enums.TidhiState PreviousTidhiState)
        {
            bool RetValue = false;

            TidhiRoutineItem NextItem = new TidhiRoutineItem(CurrentPadakam + 1, m_Year, m_Date.AddDays(1), CurrentTidhi, CurrentMasam, PreviousTidhiState,
                m_RaviRoutines, m_ChandraRoutines, m_DinamuRoutines, m_CurrentyearDetails);
            NextItem.Calculate(true, this, (DinamuRoutineItem)m_DinamuRoutines[CurrentPadakam]);
            Rasi EndTime = new Rasi(NextItem.TidhiTime);
            if ((CurrentTime + EndTime) > new Rasi(0, 1, 30, 0))
            {
                RetValue = true;
            }
            return RetValue;
        }
    }
}
